package cc.eddic.pratice.programmingparadigms.nginxlog.impl;

import cc.eddic.pratice.programmingparadigms.nginxlog.LogItem;
import cc.eddic.pratice.programmingparadigms.nginxlog.LogReport;
import cc.eddic.pratice.programmingparadigms.nginxlog.NginxLogItem;
import cc.eddic.pratice.programmingparadigms.nginxlog.PageViewsAndUniqueVisitors;


import java.util.AbstractMap;

import java.util.List;
import java.util.Map;

import java.util.stream.Collectors;

public class LogReportScwImpl implements LogReport {

    /**
     * 统计 PV 和 UV
     *
     * @param items NginxLogItem 列表
     * @return PageViewsAndUniqueVisitors 对象
     */
    @Override
    public PageViewsAndUniqueVisitors pageViewsAndUniqueVisitors(List<NginxLogItem> items) {
        long pageViews = items.size();
        Map<String, Long> uniqueVistorsMap = items.stream()
                .collect(Collectors.groupingBy(pv -> pv.getIp() + pv.getUserAgent(), Collectors.counting()));
        long uniqueVisitors = uniqueVistorsMap.values().size();
        return new PageViewsAndUniqueVisitors(pageViews, uniqueVisitors);
    }

    /**
     * 按小时统计 PV 和 UV
     * 12
     *
     * @param items NginxLogItem 列表
     * @return Map，key 为小时，value 为 PageViewsAndUniqueVisitors 对象
     */
    @Override
    public Map<Integer, PageViewsAndUniqueVisitors> pageViewsAndUniqueVisitorsByHour(List<NginxLogItem> items) {

        return items.stream()
                .collect(Collectors.groupingBy(time ->
                        Integer.parseInt(time.getTime().substring(12, 14))))
                .entrySet().stream().map(entry -> new AbstractMap.SimpleEntry<>(
                        entry.getKey(),
                        pageViewsAndUniqueVisitors(entry.getValue()
                        ))).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    /**
     * 按 path 统计 PV 和 UV （统计结果按照 PV 降序排列）
     *
     * @param items LogItem 列表
     * @return PathModel 列表
     */
    @Override
    public List<PathModel> pageViewsAndUniqueVisitorsByPath(List<LogItem> items) {
        return null;
    }
}
